package cn.chiship.framework.upms.biz.user.controller;

import cn.chiship.framework.common.annotation.SystemOptionAnnotation;
import cn.chiship.framework.common.enums.BusinessTypeEnum;
import cn.chiship.framework.upms.biz.user.entity.UpmsOrganization;
import cn.chiship.framework.upms.biz.user.entity.UpmsOrganizationExample;
import cn.chiship.framework.upms.biz.user.pojo.dto.*;
import cn.chiship.framework.upms.biz.user.service.UpmsOrganizationService;
import cn.chiship.sdk.core.annotation.Authorization;
import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.base.constants.BaseConstants;
import cn.chiship.sdk.core.util.StringUtil;
import cn.chiship.sdk.framework.base.BaseController;
import cn.chiship.sdk.framework.base.BaseService;
import cn.chiship.sdk.framework.pojo.vo.TreeVo;
import cn.chiship.sdk.framework.util.FrameworkUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;

/**
 * 组织控制层 2021/9/27
 *
 * @author lijian
 */
@RestController
@Authorization
@RequestMapping("/organization")
@Api(tags = "组织机构")
public class UpmsOrganizationController extends BaseController<UpmsOrganization, UpmsOrganizationExample> {

	private static final Logger LOGGER = LoggerFactory.getLogger(UpmsOrganizationController.class);

	@Resource
	private UpmsOrganizationService upmsOrganizationService;

	@Override
	public BaseService getService() {
		return upmsOrganizationService;
	}

	@ApiOperation(value = "组织结构树")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "sort", value = "排序方式", defaultValue = "-gmtModified",
					dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "name", value = "机构名称", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "pid", value = "父级", defaultValue = "0", dataTypeClass = String.class,
					paramType = "query"),
			@ApiImplicitParam(name = "category", value = "机构类型", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "type", value = "机构分类", dataTypeClass = Byte.class, paramType = "query"),

	})
	@GetMapping(value = "/loadTree")
	public ResponseEntity<BaseResult> loadTree(
			@RequestParam(required = false, defaultValue = "-gmtModified", value = "sort") String sort,
			@RequestParam(required = false, defaultValue = "", value = "name") String name,
			@RequestParam(required = false, defaultValue = "", value = "category") String category,
			@RequestParam(required = false, defaultValue = "0", value = "pid") String pid,
			@RequestParam(required = false, defaultValue = "", value = "type") Byte type) {
		UpmsOrganizationExample upmsOrganizationExample = new UpmsOrganizationExample();
		// 创造条件
		UpmsOrganizationExample.Criteria criteria = upmsOrganizationExample.createCriteria();
		criteria.andIsDeletedEqualTo(BaseConstants.NO);
		if (!StringUtil.isNullOrEmpty(name)) {
			criteria.andOrganizationNameLike("%" + name + "%");
		}
		if (!StringUtil.isNullOrEmpty(category)) {
			criteria.andOrganizationCategoryEqualTo(category);
		}
		if (!StringUtil.isNull(type)) {
			criteria.andTypeEqualTo(type);
		}
		// 排序
		upmsOrganizationExample.setOrderByClause(FrameworkUtil.formatSort(sort));
		List<UpmsOrganization> organizations = upmsOrganizationService.selectByExample(upmsOrganizationExample);

		return super.responseEntity(BaseResult.ok(assemblyOrganizationTableTree(pid, organizations)));
	}

	@ApiOperation(value = "组织结构树(统一为TreeVo)")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "sort", value = "排序方式", defaultValue = "-gmtModified",
					dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "pid", value = "父级", defaultValue = "0", dataTypeClass = String.class,
					paramType = "query"),
			@ApiImplicitParam(name = "category", value = "机构类型", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "type", value = "机构分类", dataTypeClass = Byte.class, paramType = "query"), })
	@GetMapping(value = "loadTreeVo")
	public ResponseEntity<BaseResult> loadTreeVo(
			@RequestParam(required = false, defaultValue = "", value = "category") String category,
			@RequestParam(required = false, defaultValue = "0", value = "pid") String pid,
			@RequestParam(required = false, defaultValue = "", value = "type") Byte type) {
		UpmsOrganizationExample organizationExample = new UpmsOrganizationExample();
		UpmsOrganizationExample.Criteria criteria = organizationExample.createCriteria()
				.andIsDeletedEqualTo(BaseConstants.NO);

		if (!StringUtil.isNullOrEmpty(category)) {
			criteria.andOrganizationCategoryEqualTo(category);
		}
		if (!StringUtil.isNull(type)) {
			criteria.andTypeEqualTo(type);
		}

		organizationExample.setOrderByClause(FrameworkUtil.formatSort("-sortOrders"));
		List<UpmsOrganization> organizations = upmsOrganizationService.selectByExample(organizationExample);
		List<TreeVo> treeVos = assemblyOrganization(pid, organizations);

		return super.responseEntity(BaseResult.ok(treeVos));
	}

	@ApiOperation(value = "根据父级加载机构")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "pid", value = "父级", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "category", value = "机构类型", dataTypeClass = String.class, paramType = "query"),

	})
	@GetMapping(value = "/loadByPid")
	public ResponseEntity<BaseResult> loadByPid(
			@RequestParam(required = false, defaultValue = "0", value = "pid") String pid,
			@RequestParam(required = false, defaultValue = "", value = "category") String category) {
		UpmsOrganizationExample upmsOrganizationExample = new UpmsOrganizationExample();
		// 创造条件
		UpmsOrganizationExample.Criteria criteria = upmsOrganizationExample.createCriteria();
		criteria.andIsDeletedEqualTo(BaseConstants.NO).andPidEqualTo(pid);
		if (!StringUtil.isNullOrEmpty(category)) {
			criteria.andOrganizationCategoryEqualTo(category);
		}
		upmsOrganizationExample.setOrderByClause(FrameworkUtil.formatSort("-sortOrders"));
		return super.responseEntity(BaseResult.ok(upmsOrganizationService.selectByExample(upmsOrganizationExample)));
	}

	@SystemOptionAnnotation(option = BusinessTypeEnum.SYSTEM_OPTION_SAVE, describe = "保存单位机构")
	@ApiOperation(value = "保存单位机构")
	@PostMapping(value = "saveUnit")
	public ResponseEntity<BaseResult> saveUnit(@RequestBody @Valid UpmsUnitDto upmsUnitDto) {

		UpmsOrganization upmsOrganization = new UpmsOrganization();
		BeanUtils.copyProperties(upmsUnitDto, upmsOrganization);
		upmsOrganization.setType(Byte.valueOf("1"));
		return super.responseEntity(super.save(upmsOrganization));

	}

	@SystemOptionAnnotation(option = BusinessTypeEnum.SYSTEM_OPTION_UPDATE, describe = "更新单位机构")
	@ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "主键", required = true, dataTypeClass = String.class,
			paramType = "path"), })
	@ApiOperation(value = "更新单位机构")
	@PostMapping(value = "updateUnit/{id}")
	public ResponseEntity<BaseResult> updateUnit(@PathVariable("id") String id,
			@RequestBody @Valid UpmsUnitDto upmsUnitDto) {
		UpmsOrganization upmsOrganization = new UpmsOrganization();
		BeanUtils.copyProperties(upmsUnitDto, upmsOrganization);
		upmsOrganization.setType(Byte.valueOf("1"));
		return super.responseEntity(super.update(id, upmsOrganization));
	}

	@SystemOptionAnnotation(option = BusinessTypeEnum.SYSTEM_OPTION_UPDATE, describe = "组织调整")
	@ApiOperation(value = "组织调整")
	@PostMapping(value = "adjustment")
	public ResponseEntity<BaseResult> adjustment(
			@RequestBody @Valid UpmsOrganizationAdjustmentDto organizationAdjustmentDto) {
		return super.responseEntity(upmsOrganizationService.adjustment(organizationAdjustmentDto.getOrganizationId(),
				organizationAdjustmentDto.getTargetOrganizationId()));
	}

	@ApiImplicitParams({
			@ApiImplicitParam(name = "type", value = "机构类型(1:机构   2:部门)", defaultValue = "1",
					dataTypeClass = Byte.class, paramType = "query"),
			@ApiImplicitParam(name = "pid", value = "父级", defaultValue = "0", dataTypeClass = String.class,
					paramType = "query"), })
	@SystemOptionAnnotation(describe = "生成组织机构编码")
	@ApiOperation(value = "生成组织机构编码")
	@GetMapping(value = "generateOrgCode")
	public ResponseEntity<BaseResult> generateOrgCode(@RequestParam(value = "pid") String pid,
			@RequestParam(value = "type") Byte type) {
		return super.responseEntity(upmsOrganizationService.generateOrgCode(pid, type));
	}

	@SystemOptionAnnotation(describe = "生成邀请码")
	@ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "主键", required = true, dataTypeClass = String.class,
			paramType = "path"), })
	@ApiOperation(value = "生成邀请码")
	@GetMapping(value = "invitationCode/{id}")
	public ResponseEntity<BaseResult> invitationCode(@PathVariable("id") String id) {
		return super.responseEntity(upmsOrganizationService.invitationCode(id));
	}

	@SystemOptionAnnotation(describe = "根据邀请码获取机构信息")
	@ApiImplicitParams({ @ApiImplicitParam(name = "code", value = "邀请码", required = true, dataTypeClass = String.class,
			paramType = "path"), })
	@ApiOperation(value = "根据邀请码获取机构信息")
	@PostMapping(value = "getByInvitation/{code}")
	public ResponseEntity<BaseResult> getByInvitation(@PathVariable("code") String code) {
		return super.responseEntity(upmsOrganizationService.getByInvitation(code));
	}

	// -----------------------------部门相关开始----------------------------------

	@SystemOptionAnnotation(option = BusinessTypeEnum.SYSTEM_OPTION_SAVE, describe = "保存单位部门")
	@ApiOperation(value = "保存单位部门")
	@PostMapping(value = "saveDept")
	public ResponseEntity<BaseResult> saveDept(@RequestBody @Valid UpmsDepartmentDto upmsDepartmentDto) {
		UpmsOrganization upmsOrganization = new UpmsOrganization();
		BeanUtils.copyProperties(upmsDepartmentDto, upmsOrganization);
		upmsOrganization.setType(Byte.valueOf("2"));
		return super.responseEntity(super.save(upmsOrganization));
	}

	@SystemOptionAnnotation(option = BusinessTypeEnum.SYSTEM_OPTION_UPDATE, describe = "更新单位部门")
	@ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "主键", required = true, dataTypeClass = String.class,
			paramType = "path"), })
	@ApiOperation(value = "更新单位部门")
	@PostMapping(value = "updateDept/{id}")
	public ResponseEntity<BaseResult> update(@PathVariable("id") String id,
			@RequestBody @Valid UpmsDepartmentDto upmsDepartmentDto) {

		UpmsOrganization upmsOrganization = new UpmsOrganization();
		BeanUtils.copyProperties(upmsDepartmentDto, upmsOrganization);
		upmsOrganization.setId(id);
		upmsOrganization.setType(Byte.valueOf("2"));
		return super.responseEntity(super.update(id, upmsOrganization));
	}

	@SystemOptionAnnotation(option = BusinessTypeEnum.SYSTEM_OPTION_REMOVE, describe = "删除数据")
	@ApiOperation(value = "删除数据")
	@PostMapping(value = "remove")
	public ResponseEntity<BaseResult> remove(@RequestBody @Valid List<String> ids) {
		return super.responseEntity(upmsOrganizationService.removeOrg(ids));
	}

	@SystemOptionAnnotation(option = BusinessTypeEnum.SYSTEM_OPTION_SAVE, describe = "组织添加用户")
	@ApiOperation(value = "设置负责人")
	@PostMapping(value = "setChargePerson")
	public ResponseEntity<BaseResult> setChargePerson(
			@RequestBody @Valid UpmsOrganizationChargePersonDto organizationChargePersonDto) {
		return super.responseEntity(
				upmsOrganizationService.setChargePerson(organizationChargePersonDto.getOrganizationId(),
						organizationChargePersonDto.getUserId(), organizationChargePersonDto.getRealName()));
	}

	@SystemOptionAnnotation(option = BusinessTypeEnum.SYSTEM_OPTION_OTHER, describe = "解散企业")
	@ApiOperation(value = "解散企业")
	@PostMapping(value = "dissolution")
	public ResponseEntity<BaseResult> dissolution(@RequestBody @Valid String orgId) {
		return super.responseEntity(upmsOrganizationService.dissolution(orgId));
	}

	private List<JSONObject> assemblyOrganizationTableTree(String pid, List<UpmsOrganization> organizations) {
		organizations.sort((o1, o2) -> o2.getSortOrders().compareTo(o1.getSortOrders()));
		List<JSONObject> treeVos = new ArrayList<>();
		for (UpmsOrganization organization : organizations) {
			List<String> pids = Arrays.asList(organization.getPid().split(";"));
			if (pids.contains(pid)) {
				treeVos.add(JSON.parseObject(JSON.toJSONString(organization)));
			}
		}
		for (JSONObject treeVo : treeVos) {
			List<JSONObject> children = assemblyOrganizationTableTree(treeVo.getString("id"), organizations);
			if (!children.isEmpty()) {
				treeVo.put("children", children);
			}
		}
		return treeVos;
	}

	private List<TreeVo> assemblyOrganization(String pid, List<UpmsOrganization> organizations) {
		organizations.sort((o1, o2) -> o2.getSortOrders().compareTo(o1.getSortOrders()));
		List<TreeVo> treeVos = new ArrayList<>();
		for (UpmsOrganization organization : organizations) {
			List<String> pids = Arrays.asList(organization.getPid().split(";"));
			if (pids.contains(pid)) {
				TreeVo treeVo = new TreeVo();
				treeVo.setId(organization.getId());
				treeVo.setLeaf(false);
				treeVo.setLabel(organization.getOrganizationName());
				treeVo.setExt(StringUtil.getString(organization.getType()));
				treeVo.setExt1(pid);
				treeVos.add(treeVo);
			}
		}
		for (TreeVo treeVo : treeVos) {
			List<TreeVo> children = assemblyOrganization(treeVo.getId(), organizations);
			treeVo.setChildren(children);
			if (treeVo.getChildren().isEmpty()) {
				treeVo.setLeaf(true);
			}
		}
		return treeVos;
	}

}
